package pagedto

import (
	"fmt"
	"gitee.com/ichub/webcli/common/base/baseconsts"
	"gitee.com/ichub/webcli/common/base/basedto"
	"gitee.com/ichub/webcli/common/base/baseutils"
	"gitee.com/ichub/webcli/common/base/baseutils/jsonutils"
	"gitee.com/ichub/webcli/common/base/baseutils/stringutils"
	"gitee.com/ichub/webcli/common/base/pagedto/pagebase"
	"gitee.com/ichub/webcli/common/dbcontent"
	"gitee.com/ichub/webcli/common/ichubcontext"
	"gitee.com/ichub/webcli/common/ichublog"
	"github.com/jinzhu/gorm"
	"github.com/sirupsen/logrus"
)

/*
@Title    文件名称: IchubPageRequest.go
@Description  描述:  IchubPageRequest

@Author  作者: leijianming@163.com  时间(2024-02-21 22:38:21)
@Update  作者: leijianming@163.com  时间(2024-02-21 22:38:21)
*/
const (
	OrderAsc  = "asc"
	OrderDesc = "desc"
)

type IchubPageRequest struct {
	basedto.BaseEntity `json:"-"`

	//每页记录数
	PageSize int `json:"page_size"`
	//当前页码
	PageCurrent int `json:"current"`
	//排序字段数组
	OrderBys []*pagebase.OrderByDto `json:"order_by"`
	//查询字段条件
	Fields []*pagebase.IchubQueryField `json:"fields"`

	//Param interface{} `json:"param,omitempty"`
}

func NewPageRequest(pageSize int, pageCurrent int) *IchubPageRequest {
	var pageRequest = &IchubPageRequest{
		PageSize:    pageSize,
		PageCurrent: pageCurrent,

		OrderBys: []*pagebase.OrderByDto{},
		Fields:   make([]*pagebase.IchubQueryField, 0),
	}

	pageRequest.InitProxy(pageRequest)
	return pageRequest
}

func NewIchubPageRequest() *IchubPageRequest {

	return NewPageRequest(
		baseconsts.PAGE_SIZE_DEFAULT,
		baseconsts.PAGE_CURRENT)
}
func (this *IchubPageRequest) Clear() {
	this.PageSize = baseconsts.PAGE_SIZE_DEFAULT
	this.PageCurrent = baseconsts.PAGE_CURRENT

	this.OrderBys = []*pagebase.OrderByDto{}
	this.Fields = make([]*pagebase.IchubQueryField, 0)
}

func (this *IchubPageRequest) GetDB() *gorm.DB {

	return dbcontent.GetDB()
}

func (this *IchubPageRequest) InitPage() {
	if this.PageSize <= baseconsts.PAGE_SIZE_ZERO {

		this.PageSize = baseconsts.PAGE_SIZE_DEFAULT

	} else if this.PageSize > baseconsts.PAGE_SIZE_MAX {

		this.PageSize = baseconsts.PAGE_SIZE_MAX

	}
	if this.PageCurrent <= 0 {
		this.PageCurrent = baseconsts.PAGE_CURRENT
	}

}
func (this *IchubPageRequest) FindFieldSign(op int) pagebase.FieldSign {
	return pagebase.OpSign[op]

}

func (this *IchubPageRequest) Start() int {
	return (this.PageCurrent - 1) * this.PageSize
}
func (this *IchubPageRequest) Limit() int {
	return this.PageSize
}

func (this *IchubPageRequest) keySnake(key string) string {
	return stringutils.Camel2Case(key)
}
func (this *IchubPageRequest) CheckTyope(field string, value interface{}) {
	baseutils.CheckType(value)
}

func (this *IchubPageRequest) QueryFields(f string, opType int, opValues []interface{}) *IchubPageRequest {

	var field = pagebase.NewFields(this.keySnake(f), opType, opValues)
	this.Fields = append(this.Fields, field)

	return this
}

func (this *IchubPageRequest) Eq(field string, opValues interface{}) *IchubPageRequest {

	return this.QueryFields(field, pagebase.Eq, []interface{}{opValues})
}
func (this *IchubPageRequest) Ge(field string, opValue interface{}) *IchubPageRequest {

	return this.QueryFields(field, pagebase.Ge, []interface{}{opValue})
}
func (this *IchubPageRequest) Le(field string, opValue interface{}) *IchubPageRequest {

	return this.QueryFields(field, pagebase.Le, []interface{}{opValue})
}
func (this *IchubPageRequest) Lt(field string, opValue interface{}) *IchubPageRequest {

	return this.QueryFields(field, pagebase.Lt, []interface{}{opValue})
}
func (this *IchubPageRequest) Gt(field string, opValue interface{}) *IchubPageRequest {

	return this.QueryFields(field, pagebase.Gt, []interface{}{opValue})
}
func (this *IchubPageRequest) In(field string, opValues []interface{}) *IchubPageRequest {

	return this.QueryFields(field, pagebase.In, opValues)
}

func (this *IchubPageRequest) NotIn(field string, opValues []interface{}) *IchubPageRequest {

	return this.QueryFields(field, pagebase.NotIn, opValues)
}
func (this *IchubPageRequest) Like(field string, opValue interface{}) *IchubPageRequest {

	return this.QueryFields(field, pagebase.Like, []interface{}{opValue})
}

func (this *IchubPageRequest) NotLike(field string, opValue interface{}) *IchubPageRequest {

	return this.QueryFields(field, pagebase.NotLike, []interface{}{opValue})
}
func (this *IchubPageRequest) Between(field string, opValues []interface{}) *IchubPageRequest {

	return this.QueryFields(field, pagebase.Between, opValues)
}
func (this *IchubPageRequest) NotBetween(field string, opValues []interface{}) *IchubPageRequest {

	return this.QueryFields(field, pagebase.NotBetween, opValues)
}
func (this *IchubPageRequest) OrderBy(field string, sort string) *IchubPageRequest {

	var orderby = pagebase.OrderBy(field, sort)
	this.OrderBys = append(this.OrderBys, orderby)
	return this
}

func (this *IchubPageRequest) OrderByAsc(field string) *IchubPageRequest {

	return this.OrderBy(field, OrderAsc)
}
func (this *IchubPageRequest) OrderByDesc(field string) *IchubPageRequest {

	return this.OrderBy(field, OrderDesc)
}

func (this *IchubPageRequest) ToMap() (*map[string]interface{}, error) {
	var str = jsonutils.ToJsonPretty(this)
	m, err := jsonutils.MapFromJson(str)
	if err != nil {
		logrus.Error(err)
	}
	return m, err

}

//update

func (this *IchubPageRequest) FindByTable(table string, result interface{}) error {

	dbc := this.GetDB().Table(table)
	dbc = this.BuildWhere(dbc)
	dbc = this.Order(dbc)
	dbc = this.SetLimit(dbc)
	dbc = dbc.Find(result)

	return dbc.Error
}

func (daoInst *IchubPageRequest) Insert(model interface{}) (interface{}, error) {

	err := dbcontent.GetDB().Create(model).Error
	if err != nil {
		logrus.Error(err.Error())

	}

	return model, err
}
func (daoInst *IchubPageRequest) Update(model interface{}, pkey int64) (interface{}, error) {

	err := dbcontent.GetDB().Model(model).Where("rule_id=?", pkey).Updates(model).Error
	if err != nil {
		logrus.Error(err.Error())
		return -1, err
	}
	return model, err

}

func (this *IchubPageRequest) FindBy(model interface{}, result interface{}) error {

	dbc := this.GetDB().Model(model)
	dbc = this.BuildWhere(dbc)
	dbc = this.Order(dbc)
	dbc = this.SetLimit(dbc)
	dbc = dbc.Find(result)

	return dbc.Error
}

func (this *IchubPageRequest) BuildWhere(dbc *gorm.DB) *gorm.DB {

	this.InitPage()
	if this.Fields == nil {
		return dbc
	}
	for _, b := range this.Fields {

		if b.OpType == pagebase.OpSign[pagebase.Between] {
			dbc = dbc.Where(fmt.Sprintf("%s BETWEEN ? and ?", b.Field),
				b.Values[0], b.Values[1])
		}
		if b.OpType == pagebase.OpSign[pagebase.NotBetween] {
			dbc = dbc.Where(fmt.Sprintf("%s Not BETWEEN ? and ?", b.Field),
				b.Values[0], b.Values[1])
		}

		if b.OpType == pagebase.OpSign[pagebase.Ge] {
			dbc = dbc.Where(fmt.Sprintf("%s >= ?", b.Field), b.Values[0])
		}
		if b.OpType == pagebase.OpSign[pagebase.Gt] {
			dbc = dbc.Where(fmt.Sprintf("%s > ?", b.Field), b.Values[0])
		}
		if b.OpType == pagebase.OpSign[pagebase.Le] {
			dbc = dbc.Where(fmt.Sprintf("%s <= ?", b.Field), b.Values[0])
		}
		if b.OpType == pagebase.OpSign[pagebase.Lt] {
			dbc = dbc.Where(fmt.Sprintf("%s < ?", b.Field), b.Values[0])
		}
		if b.OpType == pagebase.OpSign[pagebase.Eq] {
			dbc = dbc.Where(fmt.Sprintf("%s = ?", b.Field), b.Values[0])
		}
		if b.OpType == pagebase.OpSign[pagebase.Ne] {
			dbc = dbc.Where(fmt.Sprintf("%s != ?", b.Field), b.Values[0])
		}
		if b.OpType == pagebase.OpSign[pagebase.In] {

			dbc = dbc.Where(fmt.Sprintf("%s in (%s)", b.Field, b.Values2InStr()))
		}
		if b.OpType == pagebase.OpSign[pagebase.NotIn] {
			dbc = dbc.Where(fmt.Sprintf("%s not in (%s)", b.Field, b.Values2InStr()))
		}
		if b.OpType == pagebase.OpSign[pagebase.Like] {
			var sval = baseutils.Any2Str(b.Values[0])
			dbc = dbc.Where(fmt.Sprintf("%s like ?", b.Field), "'%"+sval+"%'")
		}
		if b.OpType == pagebase.OpSign[pagebase.NotLike] {
			var sval = baseutils.Any2Str(b.Values[0])
			dbc = dbc.Where(fmt.Sprintf("%s not like ?", b.Field), "'%"+sval+"%'")
		}

	}

	return dbc
}

func (this *IchubPageRequest) SetLimit(dbc *gorm.DB) *gorm.DB {
	this.InitPage()
	return dbc.Offset(this.Start()).Limit(this.Limit())

}
func (this *IchubPageRequest) Order(dbc *gorm.DB) *gorm.DB {
	if len(this.OrderBys) > 0 {

		for _, orderBy := range this.OrderBys {
			dbc = dbc.Order(orderBy.ToOrderBy())
		}
	}
	return dbc
}

func (this *IchubPageRequest) Count(model interface{}) (int, error) {
	dbc := dbcontent.GetDB().Model(model)
	dbc = this.BuildWhere(dbc).Offset(0).Limit(1)
	var count int
	if err := dbc.Count(&count).Error; err != nil {
		logrus.Error(err)
		return 0, err
	}

	logrus.Info("\ncount=", count)
	return count, nil

}
func (this *IchubPageRequest) CountTable(table string) (int, error) {
	dbc := this.GetDB().Table(table)
	dbc = this.BuildWhere(dbc).Offset(0).Limit(1)
	var count int
	if err := dbc.Count(&count).Error; err != nil {
		logrus.Error(err)
		return 0, err
	}

	logrus.Info("\ncount=", count)
	return count, nil

}
func (this *IchubPageRequest) QueryTable(table string, models interface{}) *IchubPageResult {

	fileName := table + "_pagerequest.json"
	ichubcontext.CommonContext.WriteDaoFile(fileName, this.ToPrettyString())
	this.InitPage()

	count, err := this.CountTable(table)
	if err != nil {
		logrus.Error(err)
		return NewPageResultError(err.Error())
	}
	if count > 0 {
		err = this.FindByTable(table, models)
		if err != nil {
			logrus.Error(err)
			return NewPageResultError(err.Error())
		}
	}
	var result = ValueOf(this)
	result.Total = count
	result.Data = models
	fileName = table + "_pageresult.json"
	ichubcontext.CommonContext.WriteDaoFile(fileName, result.ToPrettyString())

	ichublog.Log(result)
	return result
}
func (this *IchubPageRequest) Query(model interface{}, models interface{}) *IchubPageResult {

	fileName := stringutils.NameOfType(model) + "_pagerequest.json"
	ichublog.IchubLog.Println(this.ToPrettyString())
	ichubcontext.CommonContext.WriteDaoFile(fileName, this.ToPrettyString())
	this.InitPage()

	count, err := this.Count(model)
	if err != nil {
		logrus.Error(err)
		return NewPageResultError(err.Error())
	}
	if count > 0 {
		err = this.FindBy(model, models)
		if err != nil {
			logrus.Error(err)
			return NewPageResultError(err.Error())
		}
	}
	var result = ValueOf(this)
	result.Total = count
	result.Data = models
	fileName = stringutils.NameOfType(model) + "_pageresult.json"
	ichubcontext.CommonContext.WriteDaoFile(fileName, result.ToPrettyString())

	ichublog.IchubLog.Println(result)
	return result
}

func (this *IchubPageRequest) FindById(model interface{}, key int64) (bool, error) {

	db := this.GetDB().First(model, key)
	return db.RecordNotFound(), db.Error
}
